package risoe.syslab.fhnew.gui;

/*
 * Copyright (c) 2012-2014, Technical University of Denmark (DTU)
 * All rights reserved.
 * 
 * The Flexhouse 2.0 platform ("this software") is licensed under the
 * BSD 3-clause license.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   - Neither the name of DTU nor the names of its contributors may be used to
 *     endorse or promote products derived from this software without specific
 *     prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE TECHNICAL UNIVERSITY OF DENMARK BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringReader;

import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.dom.util.DOMUtilities;
import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;

import risoe.syslab.fhnew.gui.VisualizationUpdate.CommandHolder;

/**
 * Class providing static methods related to SVG Documents
 * @author M. Svendsen
 */
public class DocumentUtils {

	/**
	 * Converts a string of serialized data back into an SVG Document
	 * @param serializedData the data to convert
	 * @return an SVGDocument
	 */
	public static SVGDocument createDocument(String serializedData){
		// Convert the serialized XML string back into a DOM Document
		if (serializedData != null){
			try{
				StringReader reader = new StringReader(serializedData);
				String uri = "ignore";
				String parser = XMLResourceDescriptor.getXMLParserClassName();
				SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
				return (SVGDocument) f.createDocument(uri, reader);			
			} catch(IOException e){};
		}
		return null;
	}

	/**
	 * Serializes a SVG Document by converting it to a string representation
	 * @param document the document to be serialized
	 * @return a string representing the serialized Document
	 */
	public static String serializeDocument(Document document){
		OutputStream output = null;
		try {
			// Just save the document as a single string
			output = new OutputStream(){
				private StringBuilder string = new StringBuilder();

				@Override
				public void write(int b) throws IOException {
					this.string.append((char) b );
				}

				@Override
				public String toString() {
					return this.string.toString();
				}
			};

			PrintWriter writer = new PrintWriter(output);
			DOMUtilities.writeDocument(document, writer);

			// Flush the stream to the writer
			writer.flush();

			// Return serialized data
			return output.toString();
		} catch (IOException e) {e.printStackTrace();}
		return null;
	}

	/**
	 * Updates the given document with the commands contained in the VisualizationCommand argument.
	 * This function is used by PluginControllers, the UIManager and remote UIViewers in order to
	 * ensure that any command will be applied in a like manner to all documents.
	 * @param command the VisualizationCommand to apply
	 * @param document the SVG Document to which the VisualizationCommand to be applied
	 */
	public static void updateDocument(VisualizationUpdate command, SVGDocument document){
		// Early exit to avoid crashes
		if (document == null) return;

		// Update all states contained in this command
		for (CommandHolder holder : command.getCommands()){
			Element element = document.getElementById(holder.getId());
			if (element != null){
				if (holder.getAttributeName().isEmpty()){
					// This signifies a text command
					element.setTextContent(holder.getCommand());
				}
				else{
					// Check whether the command contains multiple attributes
					if (holder.getAttributeName().contains(":")){
						// We have a two parameter command
						String[] params = holder.getAttributeName().split(":");

						// Get the attribute we want to change
						String attr = element.getAttribute(params[0]);

						System.out.println("attr: " + attr);

						// Execute command on second parameter
						String param = params[1];
						int startIndex = attr.indexOf(param+":");
						int endIndex = attr.indexOf(";", startIndex);

						System.out.println("indexes: "+startIndex + ", " + endIndex);

						// Find string to replace
						String toReplace = attr.substring(startIndex, endIndex);

						// Do the actual update
						attr = attr.replace(toReplace, param+":"+holder.getCommand());

						// Place attribute back in element
						element.setAttribute(params[0], attr);
					}
					else{
						// Normal single parameter command
						element.setAttribute(holder.getAttributeName(), holder.getCommand().replace("NaN", "0.0"));
					}
				}
			}
		}
	}
}

